#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#include <sys/stat.h>
#include <signal.h>
#include <execinfo.h>

/*
 * 给SIGSEGV 这个信号注册了一个处理函数 ，替代了系统默认的产生core文件的处理函数 ，
 * 当错误发生后 ，系统 发送 SIGSEGV ，然后 中断了程序 跳到 fault_trap 处理函数中去 ，处理完成后 ，
 * 再跳回来错误发生的地方 ，然后继续产生错误 ，继续发送 SIGSEGV  信号 ... 
 */

void log2file(char *fmt, ...)
{
    time_t t = time(NULL);
    if(access("./log", F_OK) != 0)
        if(mkdir("./log", 0755) == -1)  
        {
            perror("mkdir ./log failed");
            return;
        }
    char temps[500];

    strftime(temps, sizeof(temps) - 1, "./log/%Y%m%d.log", localtime(&t));     //年-月-日 时-分-秒
    
    FILE * fp = fopen(temps, "a");
    strftime(temps, sizeof(temps) - 1, "%Y-%m-%d %H:%M:%S.%u ", localtime(&t));     //年-月-日 时-分-秒

    fputs(temps, fp);
    va_list args;
    va_start(args,fmt);
    (void)vfprintf(fp, fmt, args);
    (void)vfprintf(stdout, fmt, args);
    va_end(args);

    fclose(fp);
}
 
#define SIZE 1000
void *trace_buffer[SIZE];  

void fault_trap(int n, siginfo_t *info, void *myact)  
{  
        int i, num;
        char **calls;  

        log2file("Fault address:%X\n",info->si_addr);     

        num = backtrace(trace_buffer, SIZE);  
        calls = backtrace_symbols(trace_buffer, num);  

        for (i = 0; i < num; i++)  
                printf("%s\n", calls[i]);  

        exit(1);  
}
 
 
void setuptrap()  
{  
    struct sigaction act;  

    sigemptyset(&act.sa_mask);     
    act.sa_flags=SA_SIGINFO;      
    act.sa_sigaction=fault_trap;  
    sigaction(SIGSEGV,&act,NULL);  
}
 
int main()
{
    setuptrap();

    while(1);
}
